Pratiques avancées de l’analyse géométrique des données

Author

Viviane LE HAY

Published

May 13, 2025

Atelier Méthodes CED

Ce document détaille pas à pas les étapes de réalisation des analyses géométriques les plus simples quand on débute dans l’application de cette méthode avec R studio :

Les exemples que nous utiliserons ici sont tirés de la littérature académique (avec accès aux données utilisées par leurs auteur/ices) :

Préalables : installer et charger les packages

Dans notre cas, il est possible de simplifier l’installation et le chargement des packages en faisant appel au fichier requirements.R qui liste l’ensemble des éléments nécessaires :

Code
source("requirements.R")

Exécuter la commande ci-dessus revient à installer les packages et les charger, processus sinon détaillé ci-dessous.

Installation des packages utiles

script pour chaque package : install.packages(“NomPackage”)

Liste des packages les plus utiles pour ce qui nous concerne :

  • AGD : Factoshiny, FactoMineR, FactoInvestigate,
  • Visualisation de graphes : ggplot2, shiny, ggpmisc, dplyr
Code
#install.packages("Factoshiny")
#install.packages("FactoMineR")
#install.packages("shiny")
#install.packages("ggplot2") 
#install.packages("FactoInvestigate") 
#install.packages("ggpp")
#install.packages("dplyr") 
#install.packages("ggpmisc")
#install.packages("ggrepel")
#install.packages("readxl")
#install.packages("haven")

Chargement des packages utiles

script pour chaque package : library(“NomPackage”)

Code
library(Factoshiny)
library(FactoMineR)
library(shiny)
library(ggplot2)
library(FactoInvestigate)
library(ggpp)
library(dplyr)
library(ggpmisc)
library(ggrepel)
library(readxl)
library(haven)

# TODO: vérif mais installé et chargé par défaut non ?
# Peut virer pour nettoyer ?
#library(stats)
#library(base)

Exemple 1 - Mise en oeuvre simple pour apprivoiser R et comprendre “ce que fait” l’ACP

Un mini jeu de données à 2 variables continues
–> Taux de chômage en France 2000 / 2007 (données OCDE)

Etape 1 : Import & vérification du fichier dans R (statistiques descriptives)

Opération possible via le menu déroulant de Rstudio (le fichier est dans cet exemple au format excel) :

File –> Import Dataset –> From Excel

Code
# ici il faut possiblement adapter le chemin à sa propre arborescence
ex1 <- read_excel("data/EX1_DonneesOCDE_Base2.xls")
# View(ex1)
# view vous sera utile dans Rstudio ou équivalent
# mais comme il ouvre un autre objet, on se contente ici d'afficher
# les premières lignes du fichier avec head()
head(ex1)

ex1 = c’est le nom choisi ici qui servira à appeler le jeu de données dans R dans la suite de cet exemple (vous pouvez l’appeler ‘fraise’ si vous le souhaitez : alors vous l’écrivez ainsi dans le script :

fraise <- read_excel("ex5b-trivial-acp.xls")

NB : Il est plus simple de choisir un nom court, facile à manipuler.

Statistiques descriptives (variables continues)

Code
summary(ex1)
      id             TxChmge2000      TxChmge2007     TxChmge2000CR    
 Length:95          Min.   : 5.034   Min.   : 4.478   Min.   :-1.5852  
 Class :character   1st Qu.: 8.069   1st Qu.: 6.400   1st Qu.:-0.5856  
 Mode  :character   Median : 9.277   Median : 7.341   Median :-0.1879  
                    Mean   : 9.848   Mean   : 7.625   Mean   : 0.0000  
                    3rd Qu.:10.825   3rd Qu.: 8.556   3rd Qu.: 0.3220  
                    Max.   :21.472   Max.   :12.205   Max.   : 3.8279  
 TxChmge2007CR    
 Min.   :-1.7831  
 1st Qu.:-0.6942  
 Median :-0.1611  
 Mean   : 0.0000  
 3rd Qu.: 0.5272  
 Max.   : 2.5944  

Etape 2 : Visualisation du nuage de points des variables initiales

Code
ggplot(ex1, aes(x = TxChmge2000CR, y = TxChmge2007CR)) +
  geom_point(color = "#EF6A40", size = 3) +
  geom_text(aes(label = id), hjust = -0.1, vjust = 0.5, size = 3) +
  theme_minimal() +
  labs(
    title = "Ici je peux mettre un titre",
    x = "légende pour l'axe x",
    y = "légende pour l'axe y"
  )

Dico script R

  • geom_point : taille et couleur des points
  • geom_text : label et ajustement des points
  • labs : titre du graphes et des axes

Trucs et astuces

Etiqueter sans chevauchement de labels : package ggrepel

Code
ggplot(ex1, aes(x = TxChmge2000CR, y = TxChmge2007CR)) +
  geom_point(color = "steelblue", size = 3) +
  geom_text_repel(aes(label = id), size = 3, max.overlaps = Inf) +
  theme_minimal() +
  labs(
  title = "Ici je peux mettre un titre",
    x = "légende pour l'axe x",
    y = "légende pour l'axe y"
  )

Sélectionner certains points que l’on souhaite étiqueter (et pas les autres) : packages dplyr et ggpmisc

==> J’appelle ce graphe intermédiaire “p”

Dans le script ci-dessous, c’est ce que signifie :

==> p <-

Code
# Identifier les points extrêmes à annoter (par exemple sur Y)
points_a_annoter <- ex1 %>%
  arrange(TxChmge2007CR) %>%
  slice_head(n = 5) %>%    # les 5 plus bas
  bind_rows(
    ex1 %>% arrange(desc(TxChmge2007CR)) %>% slice_head(n = 7)  # les 7 plus hauts
  )
# Ajouter aussi le point avec la valeur maximale sur l'axe X
points_max_pop <- ex1 %>% arrange(desc(TxChmge2000CR)) %>% slice_head(n = 9)

# Combiner avec les autres extrêmes
points_a_annoter <- ex1 %>%
  arrange(TxChmge2000CR) %>%
  slice_head(n = 7) %>%
  bind_rows(
    ex1 %>% arrange(desc(TxChmge2007CR)) %>% slice_head(n = (7)),
    points_max_pop
  ) %>%
  distinct()  # pour éviter les doublons

# Nuage de points avec étiquettes seulement sur les points extrêmes
p <- ggplot(ex1, aes(x = TxChmge2000CR, y = TxChmge2007CR)) +
  geom_point(color = "steelblue", size = 3) +
  geom_text_repel(
    data = points_a_annoter,
    aes(label = id),
    size = 3
  ) +
  theme_minimal() +
  labs(
 title = "Ici je peux mettre un titre",
    x = "légende pour l'axe x",
    y = "légende pour l'axe y"
  )
print(p)

Ajout de la Droite de régression au graphe “p” déjà construit

Code
library(ggpmisc)
# Nuage de points avec étiquettes seulement sur les points extrêmes
# + ajout de la droite de régression avec geom_smooth

p +
  geom_smooth(method = "lm", se = TRUE, color = "darkred") +
  stat_poly_eq(
    aes(label = paste(..eq.label.., ..rr.label.., sep = "~~~")),
    formula = y ~ x,
    parse = TRUE,
    size = 4,
    color = "darkred"
  ) 

facultatif : ACP dans Factoshiny

Factoshiny permet de faire une exploration rapide du résultat de l’analyse géométrique.

Code
# script en commentaire pour qu'il ne s'exécute pas dans le notebook
# acp <- Factoshiny(ex1)
Dès lors que l’on est dans Factoshiny, on peut cocher :

Qui fournit le script associé aux opérations menées en click-bouton.

On peut ensuite le copier-coller dans la console R : - pour garder la trace de ce que l’on a fait - pour améliorer, via le script, les graphiques initiaux réalisés par Factoshiny

ATTENTION - Pour retourner dans la console R quand on a joué avec Factoshiny (sans que R ne bugge), il ne faut pas oublier de cliquer sur :

Code
res.PCA<-PCA(ex1,quali.sup=c(1),quanti.sup=c(4,5),graph=FALSE)
plot.PCA(res.PCA,choix='var')

Code
plot.PCA(res.PCA,invisible=c('ind','ind.sup'),select='contrib  95',cex=0.5,cex.main=0.5,cex.axis=0.5,label =c('quali'))

Code
summary(res.PCA)

Call:
PCA(X = ex1, quanti.sup = c(4, 5), quali.sup = c(1), graph = FALSE) 


Eigenvalues
                       Dim.1   Dim.2
Variance               1.849   0.151
% of var.             92.458   7.542
Cumulative % of var.  92.458 100.000

Individuals (the 10 first)
                            Dist    Dim.1    ctr   cos2    Dim.2    ctr   cos2
1                       |  0.885 |  0.709  0.286  0.641 |  0.530  1.962  0.359
2                       |  1.227 | -1.168  0.776  0.906 |  0.377  0.993  0.094
3                       |  1.369 | -1.330  1.007  0.944 |  0.324  0.734  0.056
4                       |  1.416 | -1.404  1.121  0.982 |  0.187  0.245  0.018
5                       |  0.636 | -0.479  0.131  0.567 |  0.419  1.225  0.433
6                       |  2.476 |  2.352  3.148  0.902 |  0.774  4.177  0.098
7                       |  0.453 | -0.094  0.005  0.043 |  0.443  1.368  0.957
8                       |  0.732 |  0.167  0.016  0.052 |  0.712  3.542  0.948
9                       |  2.549 |  2.549  3.698  1.000 |  0.038  0.010  0.000
10                      |  0.624 |  0.622  0.220  0.992 |  0.057  0.022  0.008
                         
1                       |
2                       |
3                       |
4                       |
5                       |
6                       |
7                       |
8                       |
9                       |
10                      |

Variables
                           Dim.1    ctr   cos2    Dim.2    ctr   cos2  
TxChmge2000             |  0.962 50.000  0.925 | -0.275 50.000  0.075 |
TxChmge2007             |  0.962 50.000  0.925 |  0.275 50.000  0.075 |

Supplementary continuous variables
                           Dim.1   cos2    Dim.2   cos2  
TxChmge2000CR           |  0.962  0.925 | -0.275  0.075 |
TxChmge2007CR           |  0.962  0.925 |  0.275  0.075 |

Supplementary categories (the 10 first)
                            Dist    Dim.1   cos2 v.test    Dim.2   cos2 v.test
Ain                     |  2.231 | -2.231  1.000 -1.640 | -0.035  0.000 -0.090
Aisne                   |  2.901 |  2.742  0.894  2.017 |  0.946  0.106  2.436
Allier                  |  1.237 |  1.154  0.870  0.849 |  0.446  0.130  1.147
Alpes-de-Haute-Provence |  0.792 |  0.788  0.990  0.579 | -0.080  0.010 -0.205
Alpes-Maritimes         |  0.590 |  0.406  0.475  0.299 | -0.427  0.525 -1.101
Ardèche                 |  0.278 |  0.100  0.129  0.073 |  0.259  0.871  0.667
Ardennes                |  2.549 |  2.549  1.000  1.874 |  0.038  0.000  0.097
Ariège                  |  1.048 |  0.930  0.787  0.684 |  0.484  0.213  1.245
Aube                    |  0.624 |  0.622  0.992  0.457 |  0.057  0.008  0.146
Aude                    |  1.896 |  1.883  0.986  1.385 | -0.223  0.014 -0.574
                         
Ain                     |
Aisne                   |
Allier                  |
Alpes-de-Haute-Provence |
Alpes-Maritimes         |
Ardèche                 |
Ardennes                |
Ariège                  |
Aube                    |
Aude                    |

Exemple 2 - ACP - Article M. Safi

Etape 3 : Import & vérification du fichier dans R

(Opération également possible via le menu déroulant de Rstudio)

Code
safi <- read_excel("data/EX2_ACP_MirnaSAFI_Extract.xls")
head(safi)

safi = le nom qui servira à appeler le jeu de données dans R dans la suite de l’exercice.

Statistiques descriptives (variables continues) :

Code
summary(safi)
      app              cult             nor              mix        
 Min.   :0.0000   Min.   :0.0000   Min.   :0.0000   Min.   :0.0000  
 1st Qu.:0.2500   1st Qu.:0.2500   1st Qu.:0.2500   1st Qu.:0.3333  
 Median :0.5000   Median :0.4286   Median :0.5000   Median :0.5000  
 Mean   :0.4451   Mean   :0.4624   Mean   :0.4587   Mean   :0.5543  
 3rd Qu.:0.7500   3rd Qu.:0.6667   3rd Qu.:0.6667   3rd Qu.:0.7500  
 Max.   :1.0000   Max.   :1.0000   Max.   :1.0000   Max.   :1.0000  
      eco            inat3          
 Min.   :0.0000   Length:8862       
 1st Qu.:0.3611   Class :character  
 Median :0.4722   Mode  :character  
 Mean   :0.4788                     
 3rd Qu.:0.5833                     
 Max.   :1.0000                     
Code
#desc(safi) # Error in xtfrm.data.frame(x) : cannot xtfrm data frames
# TODO: verif

Etape 4 facultatif : ACP dans Factoshiny

Factoshiny permet de faire une exploration rapide du résultat de l’analyse géométrique.

Code
# script en commentaire pour qu'il ne s'exécute pas dans le notebook
# acp <- Factoshiny(safi)

Dès lors que l’on est dans Factoshiny, on peut cocher :

Il devient possible de le copier-coller dans la console R :

  1. pour garder la trace de ce que l’on a fait

  2. pour améliorer, via le script, les graphiques initiaux réalisés par Factoshiny

ATTENTION - Pour retourner dans la console R quand on a joué avec Factoshiny (sans que R ne bugge), il ne faut pas oublier de cliquer sur :

Code
# graphiques initiaux réalisés dans Factoshiny
res.PCA<-PCA(safi,quali.sup=c(6),graph=FALSE)
plot.PCA(res.PCA,choix='var')

Code
plot.PCA(res.PCA,invisible=c('ind.sup'),habillage=6,cex=0.8,cex.main=0.8,cex.axis=0.8,label =c('quali', cex = 3, col = "black"))

Code
plot.PCA(res.PCA,invisible=c('ind.sup'),cex=1.2,cex.main=1.2,cex.axis=1.2,label =c('quali'))

Code
summary(res.PCA)

Call:
PCA(X = safi, quali.sup = c(6), graph = FALSE) 


Eigenvalues
                       Dim.1   Dim.2   Dim.3   Dim.4   Dim.5
Variance               2.625   0.685   0.645   0.599   0.446
% of var.             52.502  13.706  12.901  11.981   8.911
Cumulative % of var.  52.502  66.208  79.108  91.089 100.000

Individuals (the 10 first)
                    Dist    Dim.1    ctr   cos2    Dim.2    ctr   cos2    Dim.3
1               |  1.733 | -0.331  0.000  0.036 |  1.333  0.029  0.591 |  1.000
2               |  1.970 |  1.611  0.011  0.668 |  0.991  0.016  0.253 |  0.409
3               |  2.468 |  1.906  0.016  0.596 |  0.850  0.012  0.119 | -1.143
4               |  2.126 |  1.070  0.005  0.253 | -1.556  0.040  0.536 | -0.039
5               |  2.714 |  2.084  0.019  0.589 | -0.073  0.000  0.001 |  0.507
6               |  1.626 | -0.817  0.003  0.252 |  0.972  0.016  0.357 | -0.560
7               |  1.627 |  1.437  0.009  0.781 |  0.442  0.003  0.074 |  0.132
8               |  1.964 |  1.191  0.006  0.367 |  0.872  0.013  0.197 | -0.115
9               |  2.061 | -1.678  0.012  0.663 |  0.544  0.005  0.070 | -0.107
10              |  2.410 | -1.703  0.012  0.500 |  0.242  0.001  0.010 |  1.051
                   ctr   cos2  
1                0.017  0.333 |
2                0.003  0.043 |
3                0.023  0.215 |
4                0.000  0.000 |
5                0.004  0.035 |
6                0.005  0.119 |
7                0.000  0.007 |
8                0.000  0.003 |
9                0.000  0.003 |
10               0.019  0.190 |

Variables
                   Dim.1    ctr   cos2    Dim.2    ctr   cos2    Dim.3    ctr
app             |  0.727 20.119  0.528 | -0.498 36.178  0.248 | -0.165  4.237
cult            |  0.780 23.189  0.609 | -0.234  7.962  0.055 | -0.266 10.959
nor             |  0.693 18.273  0.480 |  0.532 41.344  0.283 | -0.404 25.321
mix             |  0.709 19.136  0.502 | -0.063  0.574  0.004 |  0.521 42.134
eco             |  0.711 19.282  0.506 |  0.309 13.941  0.096 |  0.335 17.349
                  cos2  
app              0.027 |
cult             0.071 |
nor              0.163 |
mix              0.272 |
eco              0.112 |

Supplementary categories
                     Dist     Dim.1    cos2  v.test     Dim.2    cos2  v.test  
Afrique         |   0.508 |  -0.200   0.154  -3.509 |  -0.237   0.218  -8.157 |
Algerie         |   0.582 |  -0.519   0.798 -13.427 |  -0.179   0.095  -9.047 |
Asie du Sud-Est |   0.951 |   0.828   0.758  11.697 |  -0.262   0.076  -7.244 |
Autres          |   0.619 |   0.267   0.185   2.798 |  -0.474   0.585  -9.728 |
Espagne         |   1.650 |   1.646   0.995  39.123 |   0.013   0.000   0.593 |
Inconnue        |   0.173 |  -0.015   0.007  -0.108 |  -0.116   0.448  -1.663 |
Maroc           |   0.674 |  -0.638   0.898 -16.711 |  -0.155   0.053  -7.956 |
Portugal        |   0.932 |   0.768   0.678  19.409 |   0.452   0.235  22.371 |
Turquie         |   1.211 |  -1.147   0.899 -30.850 |   0.188   0.024   9.917 |
                  Dim.3    cos2  v.test  
Afrique           0.033   0.004   1.154 |
Algerie          -0.066   0.013  -3.449 |
Asie du Sud-Est  -0.305   0.103  -8.687 |
Autres           -0.259   0.175  -5.483 |
Espagne           0.029   0.000   1.401 |
Inconnue          0.024   0.019   0.350 |
Maroc             0.139   0.043   7.346 |
Portugal         -0.127   0.018  -6.467 |
Turquie           0.145   0.014   7.861 |
Code
dimdesc(res.PCA)
$Dim.1

Link between the variable and the continuous variables (R-square)
=================================================================================
     correlation p.value
cult   0.7802199       0
app    0.7267331       0
eco    0.7114549       0
mix    0.7087579       0
nor    0.6925975       0

Link between the variable and the categorical variable (1-way anova)
=============================================
             R2 p.value
inat3 0.3320511       0

Link between variable and the categories of the categorical variables
================================================================
                        Estimate       p.value
inat3=Espagne          1.5358563  0.000000e+00
inat3=Portugal         0.6578828  1.078244e-85
inat3=Asie du Sud-Est  0.7179271  7.824658e-32
inat3=Autres           0.1568047  5.141114e-03
inat3=Afrique         -0.3094177  4.487460e-04
inat3=Algerie         -0.6290998  1.666087e-41
inat3=Maroc           -0.7482676  1.176393e-63
inat3=Turquie         -1.2572278 6.552151e-221

$Dim.2

Link between the variable and the continuous variables (R-square)
=================================================================================
     correlation       p.value
nor   0.53229116  0.000000e+00
eco   0.30909691 1.740282e-195
mix  -0.06273281  3.409836e-09
cult -0.23359217 4.042234e-110
app  -0.49792202  0.000000e+00

Link between the variable and the categorical variable (1-way anova)
=============================================
              R2       p.value
inat3 0.09342934 3.261218e-182

Link between variable and the categories of the categorical variables
================================================================
                         Estimate       p.value
inat3=Portugal         0.53756860 5.040441e-114
inat3=Turquie          0.27393943  2.688997e-23
inat3=Asie du Sud-Est -0.17644534  4.034943e-13
inat3=Maroc           -0.06984291  1.589331e-15
inat3=Afrique         -0.15164993  3.042982e-16
inat3=Algerie         -0.09330319  1.218672e-19
inat3=Autres          -0.38813316  1.792162e-22

$Dim.3

Link between the variable and the continuous variables (R-square)
=================================================================================
     correlation       p.value
mix    0.5213206  0.000000e+00
eco    0.3345249 1.187163e-230
app   -0.1653199  2.477895e-55
cult  -0.2658747 2.856076e-143
nor   -0.4041385  0.000000e+00

Link between the variable and the categorical variable (1-way anova)
=============================================
              R2      p.value
inat3 0.02756394 5.741584e-49

Link between variable and the categories of the categorical variables
================================================================
                         Estimate      p.value
inat3=Turquie          0.18794537 3.442041e-15
inat3=Maroc            0.18215448 1.880371e-13
inat3=Algerie         -0.02309913 5.617878e-04
inat3=Autres          -0.21598379 4.079047e-08
inat3=Portugal        -0.08378498 9.514842e-11
inat3=Asie du Sud-Est -0.26171975 3.168040e-18

Exemple 3 - ACP - Score Epices (N. Mayer)

A VOUS DE JOUER !!

Code
#library(haven) # bug ici si on rappelle pas haven
# TODO:check pourquoi plante si rappelle pas haven. autre appel de lib entre temps qui écrase la focntion ?

epices <- read_dta("data/EX3_Epices.dta")
head(epices)
Code
# Factochiny
#acp <- Factoshiny(epices)

res.PCA<-PCA(epices,quanti.sup=c(1,2,3,4),graph=FALSE)
plot.PCA(res.PCA,choix='var',cex=0.75,cex.main=0.75,cex.axis=0.75,
         col.quanti.sup='#0000FF')

Code
plot.PCA(res.PCA)